import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

# 字符集,从暗到亮
ASCII_CHARS = ['@', '#', 'S', '%', '?', '*', '+', ';', ':', ',', '.']

def resize_image(image, new_width=100):
    width, height = image.size
    ratio = height / width
    new_height = int(new_width * ratio)
    resized_image = image.resize((new_width, new_height))
    return resized_image

def pixels_to_ascii(image):
    pixels = image.getdata()
    ascii_str = ''
    for pixel in pixels:
        ascii_str += ASCII_CHARS[int(pixel / 25)]
    return ascii_str

def frame_to_ascii(frame, width=100):
    image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    image = resize_image(image, width)
    
    ascii_str = pixels_to_ascii(image.convert('L'))
    
    ascii_img = Image.new('RGB', (image.width * 10, image.height * 10), color='black')
    draw = ImageDraw.Draw(ascii_img)
    font = ImageFont.load_default()
    
    for i, char in enumerate(ascii_str):
        x, y = (i % width) * 10, (i // width) * 10
        color = image.getpixel((i % width, i // width))
        draw.text((x, y), char, font=font, fill=color)
    
    return np.array(ascii_img)

def video_to_ascii(video_path, output_path, width=100):
    cap = cv2.VideoCapture(video_path)
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = None
    
    while cap.isOpened():
        ret, frame = cap.read()
        if ret:
            ascii_frame = frame_to_ascii(frame, width)
            if out is None:
                out = cv2.VideoWriter(output_path, fourcc, fps, (ascii_frame.shape[1], ascii_frame.shape[0]))
            out.write(ascii_frame)
        else:
            break
    
    cap.release()
    if out:
        out.release()
    cv2.destroyAllWindows()

# 使用示例
video_to_ascii('input_video.mp4', 'output_video.mp4', width=100)
